#include <iostream>
#include "TcpServer.hpp"
#include "protocol.hpp"
#include <memory>
#include <functional>
#include "CalCulate.hpp"
using namespace std;
using namespace protocol_ns;
// ./TcpServer port
void Usage(string proc)
{
    cout << "Usage:" << proc << "server-port" << endl;
}
// 传递一个请求，返回一个结果
using callback_t = function<Response(const Request &req)>; // 服务器业务处理函数指针

// 服务集群
class Service
{
public:
    Service(callback_t cb)
        : _cb(cb)
    {
    }
    // 5.给成功连接的客户端提供服务
    void ServiceHelper(socket_sptr sockptr, InetAddr client)
    {
        int sockfd = sockptr->SockFd(); // 通信文件描述符
        string clientaddr = "[" + client.Ip() + ":" + to_string(client.Port()) + "-sockfd:" + to_string(sockfd) + "]# ";
        cout << "获取了一个新的连接-ip地址:" << client.Ip().c_str() << " 端口号:" << client.Port() << endl;
        string inbuffer; // 接收缓冲区
        while (true)
        {
            sleep(1);
            Request req;
            // 1.读取信息
            int n = sockptr->Recv(&inbuffer);
            if (n < 0)
            {
                cout << "客户端  " << clientaddr << " 退出" << endl;
                break;
            }
            cout << "读取到的信息>>" << endl;
            cout << inbuffer;
            // 读到了信息
            // 2.检测信息完整度并提取一个完整的报文
            string package = Decode(inbuffer);
            if (package.empty())
            {
                // 获取到的报文不是完整的
                continue;
            }
            cout << "有效报文>>" << endl;
            cout << package;
            // 此时，获取到的报文是完整的
            // 3.反序列化
            req.Deserialize(package);
            cout << "反序列化完成" << endl;
            // 此时req中就是一个Request对象，此对象中已经获取到了信息
            // 4.业务处理
            Response resp = _cb(req);
            cout << "业务处理完成" << endl;
            // 此时，resp对象中的结果就是结构化的结果
            // 5.序列化
            string send_str;
            resp.Serialize(&send_str);

            cout << "序列化>>" << endl;
            cout << send_str;

            // 6.添加报头
            send_str = Encode(send_str);

            cout << "添加报头>>" << endl;
            cout << send_str;

            // 此时报文就是"len"\r\n"{   }"\r\n
            //  7.发送
            sockptr->Send(send_str);
            cout << "发送完成" << endl;
        }
    }

private:
    callback_t _cb;
};

int main(int argc, char *argv[])
{
    if (argc != 2)
    {
        Usage(argv[0]);
        return 1;
    }
    uint16_t port = stoi(argv[1]); // 拿到端口号

    // 应用层
    Calculate cal; // 计算类对象
    // 服务集群对象
    Service calservice(bind(&Calculate::Excute, &cal, placeholders::_1)); // 将计算类对象中的处理方法绑定给服务对象

    // 表示层
    //  TcpServer类构造需要io_service_t类型的函数指针
    //  using io_service_t = function<void(socket_sptr sockfd, InetAddr client)>; // 服务器端执行的方法
    io_service_t service = bind(&Service::ServiceHelper, &calservice, placeholders::_1, placeholders::_2);

    // 会话层
    unique_ptr<TcpServer> tsvr = make_unique<TcpServer>(port, service);
    tsvr->Loop();
    return 0;
}
